﻿using Serilog;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WCS_Core_Configuration;
using WCS_Service.DomianService.Interface;
using WCS_Service.DomianService.Models;
using WCS_Service.Enums;
using WCS_Service.Models;
using WCS_Utility.ConstString;

namespace WCS_Service.DomianService
{
    /// <summary>
    /// 公共管理资源领域服务
    /// </summary>
    public class CommonResDomainService : ICommonResDomainService
    {
        #region 属性
        //等待公共巷道通行的AGV队列
        private ConcurrentDictionary<string, WaitAgvModel> WaitCommonRoadwayQueue = new();
        ///巷道状态管理
        private ConcurrentDictionary<string, RoadWayModel> RoadwayState = new();
        private string _commonRoadwayKey;
        private string _chargeRoadwaykey;
        #endregion


        public CommonResDomainService() 
        {
            RoadwayInfoInit();
        }
        #region private
        /// <summary>
        /// 巷道配置信息读取
        /// </summary>
        /// <returns></returns>
        private async Task RoadwayInfoInit()
        {
            var infos = AppSettingsConstVars.ReadRoadWayInfos<RoadWayModel>(ConstStringData.RoadWayInfoKey);
            if (infos is null)
            {
                Log.Error($"未配置巷道信息!");
                return;
            }
            List<Task> addTask = new();
            foreach (var item in infos)
            {
                addTask.Add(AddRoadwayInfo(item));
            }
            await Task.WhenAll(addTask);
        }
        private async Task AddRoadwayInfo(RoadWayModel info)
        {
            await Task.Run(() =>
            {
                if (info.type == RoadWayType.common)
                {
                    _commonRoadwayKey = info.code;
                }
                else if (info.type == RoadWayType.charge)
                {
                    _chargeRoadwaykey = info.code;
                }
                RoadwayState.AddOrUpdate(info.code, info, (key, value) => value);
            });
        }
        #endregion

        #region public 
        public string GetCommonRoadway()
        { 
            return _commonRoadwayKey;
        }
        public async Task AddWaitCommonRoadwayQueueAsync(string opticalId, string agvId)
        {
            WaitAgvModel model = new WaitAgvModel();
            model.opticalId = opticalId;
            model.agvId = agvId;
            model.waitTime = DateTime.Now;
            WaitCommonRoadwayQueue.AddOrUpdate(opticalId, model, (key, value) => value);
        }

        public async Task<RoadWayModel> GetRaodWayStateAsync(string roadWayCode)
        {
            return await Task.Run(() => 
            {
                if (!RoadwayState.TryGetValue(roadWayCode, out RoadWayModel model))
                {
                    return null;
                }
                return model;
            });
        }

        /// <summary>
        /// 查询公共巷道的状态 true可以进入 false 不能进入
        /// </summary>
        /// <returns></returns>
        public async Task<bool> QueryCommonRoadwayStateAsync()
        {
            return await Task.Run(() =>
            {
                if (!RoadwayState.TryGetValue(_commonRoadwayKey, out RoadWayModel info))
                {
                    Log.Error($"公共巷道信息不存在!");
                    return false;
                }
                if (info.isOccupation)
                {
                    return false;
                }
                info.isOccupation = true;
                RoadwayState.AddOrUpdate(_commonRoadwayKey, info, (key, value) => value);
                return true;
            });
        }
        /// <summary>
        /// 更新巷道状态 true锁定 false 释放
        /// </summary>
        /// <returns></returns>
        public async Task<bool> RoadwayStateUpdateAsync(string roadwayCode, bool state)
        {
            return await Task.Run(() =>
            {
                if (!RoadwayState.ContainsKey(roadwayCode))
                {
                    Log.Error($"巷道不存在");
                    return false;
                }
                if (!RoadwayState.TryGetValue(roadwayCode, out RoadWayModel oldValue))
                {
                    return false;
                }
                if (oldValue.isOccupation == state)
                {
                    return false;
                }
                oldValue.isOccupation = state;
                RoadwayState.AddOrUpdate(roadwayCode, oldValue, (key, value) => value);
                return true;
            });
        }
        /// <summary>
        /// 释放公共巷道
        /// </summary>
        /// <returns></returns>
        public async Task ReleaseCommonRoadwayAsync()
        {
            if (!RoadwayState.TryGetValue(_commonRoadwayKey, out RoadWayModel info))
            {
                Log.Error($"公共巷道信息不存在!");
                return;
            }
            info.isOccupation = true;
            RoadwayState.AddOrUpdate(_commonRoadwayKey, info, (key, value) => value);
            await ReleaseWaitCommonRoadwayAsync();
        }
        /// <summary>
        /// 释放指定巷道的锁定状态
        /// </summary>
        /// <returns></returns>
        public async Task ReleaseRoadwayAsync(string roadWayId)
        {
            await Task.Run(() =>
            {
                if (RoadwayState.TryGetValue(roadWayId, out RoadWayModel info))
                {
                    Log.Error($"巷道{roadWayId}信息不存在!");
                    return;
                }
                info.isOccupation = false;
                RoadwayState.AddOrUpdate(roadWayId, info, (key, value) => value);
            });
        }
        /// <summary>
        /// 释放等待中的AGV进入公共巷道
        /// </summary>
        /// <returns></returns>
        public async Task ReleaseWaitCommonRoadwayAsync()
        {
            if (WaitCommonRoadwayQueue.Any())
            {
                var info = WaitCommonRoadwayQueue.OrderBy(w => w.Value.waitTime)?.FirstOrDefault();
                if (info is not null)
                {
                    if (!await QueryCommonRoadwayStateAsync())
                    {
                        WaitAgvModel model = new WaitAgvModel();
                        model.opticalId = info.Value.Value.opticalId;
                        model.agvId = info.Value.Value.agvId;
                        model.waitTime = DateTime.Now;
                        WaitCommonRoadwayQueue.AddOrUpdate(info.Value.Value.opticalId, model, (key, value) => value);
                        return;
                    }
                    //AGV继续执行任务
                    //await SendContinueTaskAsync(info.Value.Value);
                    WaitCommonRoadwayQueue.Remove(info.Value.Key, out WaitAgvModel value);
                }
            }
        }
        #endregion
    }
}
